package com.gyj.user.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gyj.common.CommonResult;
import com.gyj.user.dao.UserDao;
import com.gyj.user.model.User;
import com.gyj.user.service.UserService;
import com.gyj.user.utils.ConstantKey;
import com.gyj.user.utils.DateUtils;
import com.gyj.user.utils.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
//@ContextConfiguration(classes = {RedisConfiguration.class, UserRedis.class})
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserRedis userRedis;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    private static final String key = "StringRedisTest1";

    @Override
    public User findByLoginName(String loginName) {

        return userDao.findByLoginName(loginName);
    }

    @Override
    public void initData() {
        userDao.deleteAll();
        User user = new User();
        user.setNickName("管理员");
        user.setLoginName("admin");
        user.setPassword("admin");
        user.setCreateTime(new Date());

        userDao.save(user);
        Assert.notNull(user.getId(), "用户ID不能为空！");
    }

    @Override
    public void redisInitData() {
        User user = new User();
        user.setNickName("管理员REDIS");
        user.setLoginName("adminRedis");
        user.setCreateTime(new Date());
        user.setPassword("123456");
        logger.info("key:" + this.getClass().getName() + ":userByLoginName:" + user.getLoginName());
        userRedis.deleteByKey(this.getClass().getName() + ":userByLoginName:" + user.getLoginName());
        userRedis.addUser(this.getClass().getName() + ":userByLoginName:" + user.getLoginName(), 3600L, user);

        boolean exists = userRedis.exists(key);
        if (exists) {
            userRedis.deleteByKey(key);
        }
        userRedis.addUserByStringRedis(key, user);
    }

    @Override
    public User getUserRedis(String loginName) {
        User user = userRedis.getUserByKey(this.getClass().getName() + ":userByLoginName:" + loginName);
        Assert.notNull(user, "用户为空！");
        logger.info("===user=== name:{},loginName: {}", user.getNickName(), user.getLoginName(), user.getCreateTime(), user.getPassWord());

        return user;
    }

    @Override
    public String addRedisByNickName(String nickname) {
        List<User> nickList = userDao.findByNickName(nickname);
        String key = this.getClass().getName() + ":findByNickName:" + nickname;
        String str = "";
        if (!nickList.isEmpty()) {
            str = userRedis.addUserListByStringRedis(key, nickList);
        }

        return str;
    }

    @Cacheable(value = "getUserById", key = "#id")
    @Override
    public User getUserById(int id) {
        User user = userDao.findById(id);
        return user;
    }

    @Override
    public List<User> getUserListByNickName(String nickname) {
        //从缓存中取内容
        try {
            String result = stringRedisTemplate.opsForValue().get(ConstantKey.USER_KEY + " nickname" + nickname);
            if (!StringUtils.isBlank(result)) {
                //把字符串转换成list
                //List<User> resultList = JsonUtils.jsonToList(result, User.class);
                List<User> resultList = JSONArray.parseArray(result, User.class);
                return resultList;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        List<User> nickList = userDao.findByNickName(nickname);
        //向缓存中添加内容
        try {
            if (!nickList.isEmpty()) {
                //把list转换成字符串
                //String cacheString = JsonUtils.objectToJson(nickList);
                //String cacheString = JSON.toJSONString(nickList);
                String cacheString = JSONObject.toJSONString(nickList);
                if (StringUtils.isNotBlank(cacheString)) {
                    stringRedisTemplate.opsForValue().set(ConstantKey.USER_KEY + " nickname" + nickname, cacheString);
                    //设置缓存失效时间100秒
                    stringRedisTemplate.expire(ConstantKey.USER_KEY + " nickname" + nickname, 100L, TimeUnit.SECONDS);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return nickList;
    }

    @Override
    public CommonResult<Boolean> addUserListByNickNameHash(String nickname) {
        CommonResult<Boolean> result = new CommonResult<Boolean>(true);
        //测试方法
        List<User> nickList = userDao.findByNickName(nickname);
        //向缓存中添加内容
        Map<String, Object> map = new HashMap<>();
        for (User u : nickList) {
            map.put(String.valueOf(u.getId()), u);
            stringRedisTemplate.opsForHash().put(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(u.getId()), JSONObject.toJSONString(u));
            //设置缓存失效时间100秒
            stringRedisTemplate.expire(ConstantKey.USER_HASH_TEST_KEY, 100L, TimeUnit.SECONDS);
        }
        result.setMessage("添加成功！");

        return result;
    }

    @Override
    public User getUserByIdHash(int id) {
        //从缓存中取内容
        try {
            Object result = stringRedisTemplate.opsForHash().get(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(id));
            if (result != null && result != "null") {
                //将json字符串转对象
                User user = JsonUtils.jsonToPojo((String) result, User.class);
                return user;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        User user = userDao.findById(id);
        //向缓存中添加内容
        try {
            //把对象转换成字符串
            String cacheString = JSONObject.toJSONString(user);
            if (StringUtils.isNotBlank(cacheString) && !cacheString.equals("null")) {
                stringRedisTemplate.opsForHash().put(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(id), cacheString);
                //设置失效时间，有效期到凌晨
                stringRedisTemplate.expire(ConstantKey.USER_HASH_TEST_KEY, DateUtils.getNowToNextDayTime(), TimeUnit.MILLISECONDS);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return user;
    }

    @Override
    public CommonResult<Boolean> updateUser(User user) {
        CommonResult<Boolean> result = new CommonResult<Boolean>(true);
        userDao.save(user);
        //设置缓存同步，即删除缓存
        Boolean isExist = stringRedisTemplate.opsForHash().hasKey(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(user.getId()));
        try {
            if (isExist) {
                stringRedisTemplate.opsForHash().delete(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(user.getId()));
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
            result.setMessage("更新失败:" + e.getMessage());
        }
        result.setMessage("更新成功！");
        result.setSuccess(true);

        return result;
    }

    @Override
    public CommonResult<Boolean> deleteUserById(int id) {
        CommonResult<Boolean> result = new CommonResult<Boolean>(true);
        userDao.deleteById(id);
        //设置缓存同步，即删除缓存
        Boolean isExist = stringRedisTemplate.opsForHash().hasKey(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(id));
        try {
            if (isExist) {
                stringRedisTemplate.opsForHash().delete(ConstantKey.USER_HASH_TEST_KEY, String.valueOf(id));
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
            result.setMessage("删除失败:" + e.getMessage());
        }
        result.setMessage("删除成功！");
        result.setSuccess(true);

        return result;
    }
}
